﻿// owner 蒋家伟

#include "SerialPortHardwareCompoent.h"

// qt
#include <QThread>

// jsdk
#include "TaskId.h"
#include "Dbg_Warn_Define.h"

using namespace jsdk;

OwnerPtr<jsdk::SerialPortHardwareCompoent> jsdk::SerialPortHardwareCompoent::create(IHardwareEventHandler* pHardwareEventHandler, ISerialPortEventHandler* pSerialPortEventHandler)
{
    OwnerPtr<jsdk::SerialPortHardwareCompoent> opSerialPortHardwareCompoent = NEW_AS_OWNERPTR(SerialPortHardwareCompoent);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSerialPortHardwareCompoent, L"串口硬件组件创建失败", L"蒋家伟", L"2023-08-03");
    opSerialPortHardwareCompoent->m_opSerialPortHardwareWorker.swap(SerialPortHardwareWorker::create(pHardwareEventHandler));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSerialPortHardwareCompoent->m_opSerialPortHardwareWorker, L"串口硬件工作对象创建失败", L"蒋家伟", L"2023-08-03");
    opSerialPortHardwareCompoent->m_opSerialPort.swap(ISerialPort::create(pSerialPortEventHandler));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSerialPortHardwareCompoent->m_opSerialPort, L"串口对象创建失败", L"蒋家伟", L"2023-08-03");
    opSerialPortHardwareCompoent->m_opThread.swap(NEW_AS_OWNERPTR_WITH_DELETER(QThread, ThreadDeleter));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSerialPortHardwareCompoent->m_opThread, L"硬件对象工作线程创建失败", L"蒋家伟", L"2023-08-03");
    return std::move(opSerialPortHardwareCompoent);
}

bool jsdk::SerialPortHardwareCompoent::start(
    const std::string& portName,
    int baudRate,
    short dataBits,
    short stopBits,
    short parity,
    short flowControl)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_opSerialPort && !m_opSerialPort->isOnLine(), L"硬件串口正在工作中请勿重复开始", L"蒋家伟", L"2023-07-28");
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_opThread, L"工作线程未初始化", L"蒋家伟", L"2023-07-28");
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_opSerialPortHardwareWorker, L"工作对象未初始化", L"蒋家伟", L"2023-07-28");
    // 硬件Work工作开始
    bool success = SerialPortHardwareCompoent::init();

    DBG_WARN_AND_RETURN_FALSE_UNLESS(success, L"硬件对象初始化失败 ———— [信号与槽链接]", L"蒋家伟", L"2023-07-28");
    m_opSerialPortHardwareWorker->moveToThread(m_opThread.get());
    m_opThread->start();

    // 使用的套接字开始工作
    m_opSerialPort->connected(portName, baudRate, dataBits, stopBits, parity, flowControl);
    return true;
}

bool jsdk::SerialPortHardwareCompoent::reConnect(
    const std::string& portName,
    int baudRate,
    short dataBits,
    short stopBits,
    short parity,
    short flowControl
    ) const
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_opSerialPort && !m_opSerialPort->isOnLine(), L"硬件串口正在工作中请勿重复连接", L"蒋家伟", L"2023-07-28");
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_opThread, L"工作线程未初始化", L"蒋家伟", L"2023-07-28");
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_opSerialPortHardwareWorker, L"工作对象未初始化", L"蒋家伟", L"2023-07-28");
    m_opSerialPort->reconnect(portName, baudRate, dataBits, stopBits, parity, flowControl);
    return true;
}

void jsdk::SerialPortHardwareCompoent::stop()
{
    // 可以暂停线程或者停止所有任务，或者关闭从来
}

void jsdk::SerialPortHardwareCompoent::addTask(const TaskId& taskId) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_opSerialPort, L"套接字未工作", L"蒋家伟", L"2023-07-28");
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_opThread, L"工作线程未初始化", L"蒋家伟", L"2023-07-28");

    QVariant data;
    data.setValue(taskId);
    emit addTasks(data);
}

void jsdk::SerialPortHardwareCompoent::sendMessage(std::string && msg, int64_t length) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_opSerialPort && m_opSerialPort->isOnLine(), L"套接字对象为工作", L"蒋家伟", L"2023-08-03");
    return m_opSerialPort->send(std::move(msg), length);
}

bool jsdk::SerialPortHardwareCompoent::isOnline() const
{
    if (m_opSerialPort)
    {
        return m_opSerialPort->isOnLine();
    }
    return false;
}

bool jsdk::SerialPortHardwareCompoent::init() const
{
    // 连接信号与槽
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_opSerialPortHardwareWorker, L"硬件工作对象创建错误", L"蒋家伟", L"2023-07-28");
    bool success = connect(this, SIGNAL(addTasks(QVariant)), m_opSerialPortHardwareWorker.get(), SLOT(onAddTask(QVariant)));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(success, L"硬件开始工作的信号与槽连接失败", L"蒋家伟", L"2023-07-26");
    return true;
}
